package com.example.codegenerator.common.sources;

import com.alibaba.fastjson.JSON;
import com.example.codegenerator.common.config.GeneratorConfig;
import com.example.codegenerator.common.constant.global.GeneratorConstant;
import com.example.codegenerator.common.constant.obj.GeneratorMapConstant;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.Charset;
import java.util.Map;
import java.util.Optional;

/**
 * 代码生成模板引擎
 *
 * @author Lv
 * @date 2023/11/19
 */
@SuppressWarnings("all")
@Slf4j
@Component
public class GeneratorEngine {

    @Autowired
    private VelocityEngine velocityEngine;

    /**
     * 根据模板输出代码文件
     *
     * @param dataMap          构建信息
     * @param templateFilePath 模板信息
     * @param outputFile       代码文件输出路径
     */
    @SneakyThrows
    public void writer(Map<String, Object> dataMap, String templateFilePath, String outputFile) {
        if (StringUtils.isEmpty(templateFilePath)) {
            return;
        }
        log.info("objectMap :{} , templatePath :{} ,outputFile :{}", JSON.toJSONString(dataMap), templateFilePath, outputFile);
        Template template = velocityEngine.getTemplate(templateFilePath, Charset.forName("UTF-8").name());
        FileOutputStream fos = new FileOutputStream(outputFile);
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(fos, Charset.forName("UTF-8").name()));
        template.merge(new VelocityContext(dataMap), writer);
        writer.close();
        log.info("模板:" + templateFilePath + ";  文件:" + outputFile);
    }

    @Autowired
    private GeneratorConfig generatorConfig;

    /**
     * 输出代码文件
     *
     * @param dataMap      代码生成填充信息
     * @param fileFormat   文件格式 （默认 .java ）
     * @param name         生成对象名称
     * @param outPath      代码文件输出路径
     * @param templatePath 模板路径
     */
    public void outPrint(Map<String, Object> dataMap, String fileFormat, String name, String outPath, String templatePath) {
        Map map = (Map) dataMap.get(GeneratorMapConstant.TABLE);
        String objectName = (String) map.get(name);
        Map<String, String> pathInfoMap = generatorConfig.initPathInfo();
        String path = pathInfoMap.get(outPath);

        if (null != objectName && null != path) {
            String file = String.format((path + File.separator + "%s" + Optional.ofNullable(fileFormat).orElse(GeneratorConstant.JAVA_FORMAT)), objectName);
            writer(dataMap, templateFilePath(templatePath), file);
        }
    }

    /**
     * 输出代码文件
     *
     * @param dataMap      代码生成填充信息
     * @param name         生成对象名称
     * @param outPath      代码文件输出路径
     * @param templatePath 模板路径
     */
    public void outPrint(Map<String, Object> dataMap, String name, String outPath, String templatePath) {
        outPrint(dataMap, null, name, outPath, templatePath);
    }

    /**
     * 模板文件格式
     */
    private static final String DOT_VM = ".vm";

    /**
     * 处理模板信息
     *
     * @param filePath 模板文件路径
     * @return
     */
    private String templateFilePath(String filePath) {
        if (null == filePath || filePath.contains(DOT_VM)) {
            return filePath;
        }
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(filePath).append(DOT_VM);
        return stringBuilder.toString();
    }

    /**
     * 创建文件夹
     *
     * @param path 文件夹路径
     * @return
     */
    public GeneratorEngine mkdir(String path) {
        File dir = new File(path);
        if (!dir.exists()) {
            boolean result = dir.mkdirs();
            if (result) {
                log.debug("创建目录： [" + path + "]");
            }
        }
        return this;
    }
}
